package system;

import java.util.LinkedList;
import java.util.List;

import Transporter.Transporter;
import stanowisko.Stanowisko;
import utils.Logger;
import utils.NetworkLogger;
import item.Obiekt;
import item.Samochod;
import kolejka.Kolejka;

public class MySystem {	
	int id;
	int pojemnoscSystemu;
	
	Kolejka<Samochod> kolejka;
	List<Stanowisko<Samochod>> myjnie;
	
	private NetworkLogger log;
	
	/** Do przenoszenia samochodow miedzy systemami */
	Transporter transporter;
	
	public MySystem(Kolejka<Samochod> kolejka, List<Stanowisko<Samochod>> myjnie, Transporter transporter, int pojemnoscSystemu, int id) {
		this.id = id;
		this.pojemnoscSystemu = pojemnoscSystemu;
		this.kolejka = kolejka;
		this.myjnie = myjnie;
		this.transporter = transporter;
		this.log = new NetworkLogger(false);
	}
	
	public double dajCzasNajblizszegoZdarzenia(double aktualnyCzas) {
		double czasNajblizszegoZdarzenia = Double.MAX_VALUE;

		for (Stanowisko<Samochod> myjnia : this.myjnie) { //case: myjnia zablokowana (zadanie skonczone ale jest na stanowisku)
			if (!myjnia.czyPusty() && !myjnia.czyZablokowana()
					&& myjnia.dajCzasRozpoczeciaMyciaSamochodu() + myjnia.dajCzasObslugi() < czasNajblizszegoZdarzenia) {
				czasNajblizszegoZdarzenia = myjnia.dajCzasRozpoczeciaMyciaSamochodu() + myjnia.dajCzasObslugi();
			}
		}
//		System.out.println("czas do zdarzenia: "+czasNajblizszegoZdarzenia);
		return czasNajblizszegoZdarzenia >= aktualnyCzas ? czasNajblizszegoZdarzenia : aktualnyCzas;
	}
	
	/**
	 * Metoda aktualizuje elementy w systemie: usuwa obiekty ze stanowiska
	 * jesli zostaly obsluzone i dodaje elementy w kolejce jesli jest miejsce
	 * @param aktualnyCzas - aktualny czas symulacji
	 */
	public void aktualizujElementyWSystemie(double aktualnyCzas) {
		usunElementyKtoreSieDa(aktualnyCzas);
		dodajObiektJesliSieDa(aktualnyCzas);
	}
	
		public void usunElementyKtoreSieDa(double aktualnyCzas) {
			for (Stanowisko<Samochod> myjnia : this.myjnie) {//usun te obiekty ktore mozna usunac
				if (!myjnia.czyPusty()
						&& aktualnyCzas >= myjnia.dajCzasRozpoczeciaMyciaSamochodu() + myjnia.dajCzasObslugi()) {
					this.log.logCarWashed(aktualnyCzas, myjnia.dajId(), myjnia.dajAktualnyObiekt(),
							kolejka.dajWszystkie());
					if(this.transporter == null) {
						System.out.println("Obiekt wychodzi z systemu: "+myjnia.dajAktualnyObiekt().dajID());
//						this.log.logCarWashed(aktualnyCzas, myjnia.dajId(), myjnia.dajAktualnyObiekt(),
//								kolejka.dajWszystkie());
						myjnia.usunObiekt();						
					}
					else {
						if(!myjnia.czyZablokowana()) {
							this.transporter.wylosujSystem();
						}
//						System.out.println("xx: "+this.transporter.getSystemTo().getId());
						if(this.transporter.isTransportPossible()) {
							myjnia.zablokowana(false);
//							System.out.println("!!!!!!!!!!!!!!!!!!");
				            this.log.logAddItemToQueue(aktualnyCzas, myjnia.dajAktualnyObiekt(), this.transporter.getSystemTo().getKolejka().dajWszystkie(), 
				            		this.transporter.getSystemTo().getId());
							this.transporter.transportSamochod((Samochod) myjnia.dajAktualnyObiekt());
//							this.log.logCarWashed(aktualnyCzas, myjnia.dajId(), myjnia.dajAktualnyObiekt(),
//									kolejka.dajWszystkie());
							myjnia.usunObiekt();
						}
						
						else {
							System.out.println("Blokada");
							myjnia.zablokowana(true);
						}
					}
				}//if
			}
		}
	
		public void dodajObiektJesliSieDa(double aktualnyCzas) {
			for (Stanowisko<Samochod> myjnia : this.myjnie) {
				if (myjnia.czyPusty() && !this.kolejka.czyPusty()) {	
					Samochod samochodDoMycia = this.kolejka.usunPierwszy();
					myjnia.ustawAktualnyObiekt(samochodDoMycia);	
					myjnia.ustawCzasRozpoczeciaMyciaSamochodu(aktualnyCzas);
	
					this.log.logCarStartedToWash(aktualnyCzas, myjnia.dajId(), myjnia.dajAktualnyObiekt(),
							kolejka.dajWszystkie());
//					break;
				}
			}
		}	

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getPojemnoscSystemu() {
		return pojemnoscSystemu;
	}

	public void setPojemnoscSystemu(int pojemnoscSystemu) {
		this.pojemnoscSystemu = pojemnoscSystemu;
	}

	public Kolejka<Samochod> getKolejka() {
		return kolejka;
	}

	public void setKolejka(Kolejka<Samochod> kolejka) {
		this.kolejka = kolejka;
	}

	public List<Stanowisko<Samochod>> getMyjnie() {
		return myjnie;
	}

	public void setMyjnie(List<Stanowisko<Samochod>> myjnie) {
		this.myjnie = myjnie;
	}

	public Transporter getTransporter() {
		return transporter;
	}

	public void setTransporter(Transporter transporter) {
		this.transporter = transporter;
	}
}
